local CanPoolObj = require("manager.CanPoolObj")
local Monster = class("Monster", CanPoolObj)
local GameUtils = require("utils.GameUtils")
local Vector3 = require("utils.Vector3")
local FightHelper = require("gameLogic.fight.FightHelper")
local GameConst = require("const.GameConst")

local MOVE_SPEED = 10
local SPEED_ADD = 15
local WAIT_TIME = 2

function Monster:ctor(monsterId, parent)
    self._monsterId = monsterId
    self._parent = parent
    self:_init()
end

function Monster:_init()
    self._runRadius = GameConst.MONSTER_RANDIUS
    local resName, monName = FightHelper.getMonsterTeamShowRes(self._monsterId)
    local object = G_ResourceManager:loadActor(resName)
    local gameObject = GameUtils.instantiate(object, self._parent.transform)
    local luaBehaviour = gameObject:AddComponent(typeof(CS.LuaBehaviour))
    self._controller = gameObject:AddComponent(typeof(CS.UnityEngine.CharacterController))
    local collider = gameObject:AddComponent(typeof(CS.UnityEngine.SphereCollider))
    collider.isTrigger = true
    collider.radius = GameConst.MONSTER_TRACK_RANDIUS
    self._controller.center = Vector3.new(0, 1, 0)
    luaBehaviour:SetScriptEnv(self)
    local objectName = G_ResourceManager:loadPrefabs("Prefabs/View/WorldUI/MonsterName")
    local _, nameUI = GameUtils.instantiate(objectName, gameObject.transform)
    nameUI.transform.localPosition = Vector3.new(0, 2, 0)
    nameUI.transform.localScale = Vector3.new(0.02, 0.02, 0.02)
    self._monsterName = monName
    self._nameUI = nameUI
    self._nameUI:setName(monName)
end

function Monster:reset()
    self._isFight = false
    self._waitTime = WAIT_TIME
    self._fightWaitTime = 0
    self._target = nil
    self._nameUI:setName(self._monsterName)
end

function Monster:setName(name)
    self._nameUI:setName(name)
end

function Monster:awake()
end

function Monster:start()
    self._waitTime = WAIT_TIME
    self._fightWaitTime = 0
    self._initPos = self.transform.position
    self._animator = self.gameObject:GetComponent(typeof(CS.UnityEngine.Animator))
end

function Monster:onTriggerEnter(other)
    if other:CompareTag("Player") then
        self._target = other.transform
    end
end

function Monster:onTriggerExit(other)
    if other:CompareTag("Player") then
        self._animator:SetBool("isMoving", false)
        self._target = nil
    end
end

function Monster:setFight(fight)
    self._isFight = fight
    if G_SocketManager:isContenting() then
        if fight then
            self._nameUI:setName(Lang.get("lang_monster_fighting_text", {name = self._monsterName}))
        else
            self._nameUI:setName(self._monsterName)
        end
    end
end

function Monster:setTrackTarget(targetPos)
    local distance = Vector3.distance(self.transform.position, targetPos)
    local dir = targetPos - self.transform.position
    dir = dir.normalized
    if distance > 1 then
        targetPos = self.transform.position + dir * (distance - 1)
    end
    self.transform.forward = dir
    local sequence = DOTween.Sequence()
    self._animator:SetBool("isMoving", true)
    local move = self.transform:DOMove(targetPos, 0.8)
    sequence:Append(move)
    sequence:AppendCallback(
        function()
            self._animator:SetBool("isMoving", false)
        end
    )
end

function Monster:leaveTrack()
    self._target = nil
end

function Monster:update(dt)
    if self._isFight then
        return
    end
    if self._target then
        self:_moveTarget()
    else
        self:_moveRandom()
    end
end

function Monster:_moveTarget()
    if self._fightWaitTime > 0 then
        self._fightWaitTime = self._fightWaitTime - G_Time.deltaTime
        self._target = nil
        return
    end
    if GameUtils.isNull(self._target) then
        self._target = nil
        return
    end
    if self._animator:GetBool("isMoving") == false then
        self._animator:SetBool("isMoving", true)
    end
    local myPos = self.transform.position
    local tarPos = self._target.position
    local dis = Vector3.distance(myPos, tarPos)
    if dis < 1.5 then
        self._animator:SetBool("isMoving", false)
        self._target = nil
        self._fightWaitTime = 2
        local sceneId = G_SceneManager:getCurSceneId()
        G_UserData:getGameLogic():c2sMonsterFight(sceneId, self._monsterId)
        return
    end
    self.transform:LookAt(self._target)
    local dir = self._target.position - self.transform.position
    dir = dir.normalized * SPEED_ADD
    self._controller:Move(dir * G_Time.deltaTime)
end

function Monster:monsterFight()
    local monster_team = G_UserData:getGameCache():getFight_monster_team()
    local isHaveUI = G_UIManager:isHaveUIInScene()
    if self._monsterId > 0 and monster_team == 0 and not isHaveUI then
        G_UserData:getGameCache():setFight_monster_team(self._monsterId)
        G_SignalManager:dispatch(SignalConst.EVENT_ENTER_FIGHT, self._initPos)
        self:setFight(true)
    end
end

function Monster:_moveRandom()
    if self._waitTime > 0 then
        self._waitTime = self._waitTime - G_Time.deltaTime
        return
    end
    local myPos = self.transform.position
    if not self._targetPos then
        local randomX = GameUtils.randomRadius(self._runRadius)
        local randomZ = GameUtils.randomRadius(self._runRadius)
        local targetPos = Vector3.new(self._initPos.x + randomX, myPos.y, self._initPos.z + randomZ)
        self._targetPos = targetPos
    end
    if self._animator:GetBool("isMoving") == false then
        self._animator:SetBool("isMoving", true)
    end
    self.transform:LookAt(self._targetPos)

    local pos = self.transform.position
    pos.y = pos.y + 0.6
    if Physics.Raycast(CS.UnityEngine.Ray(pos, self.transform.forward), 1) then
        self._targetPos = nil
        return
    end

    local dir = self._targetPos - self.transform.position
    dir = dir.normalized * MOVE_SPEED
    self._controller:Move(dir * G_Time.deltaTime)
    local pos = self.transform.position
    self._targetPos.y = pos.y
    local distance = Vector3.distance(pos, self._targetPos)
    if distance < 0.5 then
        self._animator:SetBool("isMoving", false)
        self._waitTime = WAIT_TIME
        self._targetPos = nil
    end
end

function Monster:setPosition(pos)
    self.transform.position = pos
end

function Monster:setScale(scale)
    self.transform.localScale = scale
end

return Monster
